/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include <stdio.h>

#include <iostream>

#include "auth/HmacSha1.h"
#include "auth/HmacSha256.h"
#include "utils/StringUtils.h"

using aliyun::auth::ISigner;
using aliyun::auth::HmacSha1;
using aliyun::auth::HmacSha256;

#define assertTrue(expr) do { \
  std::cerr << "assertTrue(" << #expr << "): "; \
  if(expr) { \
    std::cerr << "PASS!" << std::endl; \
  } else { \
    std::cerr << "FAIL!" << std::endl; \
    ::exit(-1); \
  } \
} while(0)

void testHmacSha1() {
  HmacSha1 hs;

  std::string key = "AccessSecret";
  std::string msg = "this is a HmacSha1 test.";

  unsigned char hmac[HmacSha1::DIGEST_LENTH];
  hs.HMAC_SHA1(hmac, reinterpret_cast<const unsigned char*>(key.c_str()),
               key.length(),
               reinterpret_cast<const unsigned char*>(msg.c_str()),
               msg.length());

  assertTrue(
      aliyun::utils::StringUtils::hexDump(hmac, sizeof hmac, false)
          == "47ff824f95bba3569f6bc8a91023b74b26230fad");

  assertTrue(hs.signString(msg, key) == "R/+CT5W7o1afa8ipECO3SyYjD60=");
}

void testHmac1() {
  assertTrue(
      "axE3FUHgDyfm9/+Iep0HpZXrRwE="
          == HmacSha1::getInstance()->signString(
              "GET&%2F&AccessKeyId%3Dtestid%26Action%3DDescribeRegions%26Format%3DXML"
              "%26RegionId%3Dregion1%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3DNwDAxvLU6tFE0DVb%26Sign"
              "atureVersion%3D1.0%26TimeStamp%3D2012-12-26T10%253A33%253A56Z%26Version%3D2013-01-10",
              "testsecret&"));
}

void testHmacSha256() {
  HmacSha256 hs;

  std::string msg = "this is a ShaHmac256 test.";
  std::string key = "AccessSecret";

  unsigned char hmac[32];
  hs.HMAC(hmac, reinterpret_cast<const unsigned char*>(key.c_str()),
          key.length(), reinterpret_cast<const unsigned char*>(msg.c_str()),
          msg.length());

  assertTrue(
      aliyun::utils::StringUtils::hexDump(hmac, sizeof hmac, false)
          == "3f4307077c25b5aff804e29ae71b7e3e28bd5a70cce92fa38026d0e36a742848");

  assertTrue(
      hs.signString("this is a ShaHmac256 test.", "AccessSecret")
          == "P0MHB3wlta/4BOKa5xt+Pii9WnDM6S+jgCbQ42p0KEg=");
}

int main() {
  testHmacSha1();
  testHmacSha256();
  testHmac1();
  return 0;
}

class AprGlobalWrapper {
 public:
  AprGlobalWrapper() {
    if (apr_initialize() != APR_SUCCESS) {
      ::fprintf(stderr, "apr_initialize fail");
      ::exit(-1);
    }
  }
  ~AprGlobalWrapper() {
    apr_terminate();
  }
};

static AprGlobalWrapper __aprGlobalWrapper;
